#include <iostream>
#include <fstream>
#include <list>
#include <boost/filesystem.hpp>
#include <boost/regex.hpp>
#include <tchar.h>

#include "OutputConfig.h"
#include "BasicEvent.h"
#include "AbpaFileFormat.h"

using namespace platform;
using namespace config;
using namespace events;
using namespace boost;

typedef std::list<std::string> FilesList;

// forward declarations
void getFileList(FilesList &lst);
void processFile(std::string &name);


// MAIN
int main(int argc, char *argv[]) {
	// get the list of "abpa" files (full paths)
	FilesList flist;
	getFileList(flist);

	// process all "abpa" files
	for (FilesList::iterator it = flist.begin(); it != flist.end(); ++it)
		processFile(*it);
}


typedef filesystem::path path;
typedef filesystem::directory_iterator directory_iterator;

#pragma warning( disable : 4129 )  // \. is a valid escape sequence for regex

/**
 * Returns (as in/oit parameter) a list of "abpa" file in
 * default output folder (as obtained from the registry)
 */
void getFileList(FilesList &lst) {
	OutputConfig conf;
	path out = conf.getLocation().getANSIString();

	directory_iterator end_itr; // default construction yields past-the-end
	regex abpaFile(".*\\.abpa$");
	for (directory_iterator itr(out); itr != end_itr; ++itr) {
		const path::string_type &next = itr->path().string();
		if (regex_match(next.c_str(), abpaFile))
			lst.push_back(next);		
	}
}


/**
 * Prints information for given ABPA file
 */
void processFile(std::string &name) {
	std::cout << "==========================================\nABPA FILE: "
			  << name.c_str() << '\n';

	std::ifstream instr(name.c_str(), std::ios_base::binary);
	if (!instr.is_open()) {
		std::cout << "failed to open file\n";
		return;
	}

	// read the header
	events::AbpaFileFormat abf(instr);
	std::cout << "File format is " << (abf.isValid() ? "OK" : "er");
	std::cout << " version=" << ((abf.getVersion() & 0xff000000) >> 24) << '.' << (abf.getVersion() & 0xffffff) << ", process name=" << abf.getProcessName().getANSIString()
		      << ", tick-count=" << abf.getTickCount() << '\n';

	// read events
	bool bSeenEofEvent = false;
	while (!instr.eof() && !bSeenEofEvent) {
		try {
			BasicEvent *be = BasicEvent::fromStream(instr);
			if (be != NULL) {
				std::cout << "time=" << be->getTickCount() << " (+" << (be->getTickCount() - abf.getTickCount()) << ") ";
				be->writeDebugInfo(std::cout);
				if (be->getType() == BasicEvent::EVENT_EOF)
					bSeenEofEvent = true;
				delete be;
			} else {
				std::cout << "null\n";
			}
		} catch(...) {
			std::cout << "exception while reading file\n";
		}
	}
}